package isskj.regulatory.presentation.base_mvp.api

import android.support.annotation.CallSuper
import com.google.gson.annotations.Until
import io.reactivex.*
import sskj.regulatory.data.mapper.Mapper
import sskj.regulatory.domain.fetcher.Fetcher
import sskj.regulatory.domain.fetcher.Status
import sskj.regulatory.domain.fetcher.result_listener.RequestType
import sskj.regulatory.domain.fetcher.result_listener.ResultListener
import sskj.regulatory.domain.interactor.UserInteractor
import sskj.regulatory.presentation.base_mvp.base.BaseContract
import sskj.regulatory.presentation.base_mvp.base.BasePresenter
import javax.inject.Inject


abstract class ApiPresenter<VIEW : BaseContract.View> : BasePresenter<VIEW>(), ResultListener {


    @Inject
    protected lateinit var mapper: Mapper

    @Inject
    protected lateinit var fetcher: Fetcher

    @Inject
    protected lateinit var userInteractor: UserInteractor

    private val TYPE_NONE = RequestType.TYPE_NONE
    protected val ISREGISTER = RequestType.ISREGISTER
    protected val REGISTER = RequestType.REGISTER
    protected val SITEVIDEO = RequestType.SITEVIDEO
    protected val AUTH: RequestType = RequestType.AUTH
    protected val COMMENTS = RequestType.COMMENTS
    protected val LIKE = RequestType.LIKE
    protected val SUCCESS = Status.SUCCESS
    protected val LOADING = Status.LOADING
    protected val ERROR = Status.ERROR
    protected val EMPTY_SUCCESS = Status.EMPTY_SUCCESS

    protected infix fun RequestType.statusIs(status: Status) = fetcher.getRequestStatus(this) == status

    protected val RequestType.status
        get() = fetcher.getRequestStatus(this)


    fun <TYPE> run(flowable: Flowable<TYPE>, success: (TYPE) -> Unit, error: (Throwable) -> Unit) {
        fetcher.run(flowable, success, error)
    }

    fun <TYPE> run(flowable: Flowable<TYPE>, scheduler: Scheduler, success: (TYPE) -> Unit, error: (Throwable) -> Unit) {
        fetcher.run(flowable, scheduler, success, error)
    }

    fun <TYPE> fetch(flowable: Flowable<TYPE>,
                     requestType: RequestType = TYPE_NONE, success: (TYPE) -> Unit) {
        fetcher.fetch(flowable, requestType, this, success)
    }

    fun <TYPE> fetch(observable: Observable<TYPE>,
                     requestType: RequestType = TYPE_NONE, success: (TYPE) -> Unit) {
        fetcher.fetch(observable, requestType, this, success)
    }

    fun <TYPE> fetch(single: Single<TYPE>,
                     requestType: RequestType = TYPE_NONE, success: (TYPE) -> Unit) {
        fetcher.fetch(single, requestType, this, success)
    }

    fun complete(completable: Completable,
                 requestType: RequestType = TYPE_NONE, success: () -> Unit = {}) {
        fetcher.complete(completable, requestType, this, success)
    }

    @CallSuper
    override fun onPresenterDestroy() {
        super.onPresenterDestroy()
        fetcher.clear()
    }

    @CallSuper
    override fun onRequestStart(requestType: RequestType) {
        onRequestStart()
    }

    @CallSuper
    override fun onRequestError(requestType: RequestType, errorCode: String, errorMessage: String?) {
        onRequestError(errorCode, errorMessage)
    }

    override fun onRestRequest() {
        fetch(userInteractor.refreshToken(), RequestType.REFERSH, {})
    }

    override fun onSessionError() {
        view.sessionError()
    }

    override fun onConnectError() {
        view.connectError()
    }

}